jQuery UI 1.9 Upgrade Guide


link Overview

This guide will assist in upgrading from jQuery UI 1.8.x to jQuery UI 1.9.x. All changes are listed below, organized by plugin, along with how to upgrade your code to work with jQuery UI 1.9.

link API Redesigns

jQuery UI 1.9 introduces API redesigns for Accordion, Position, Tabs, and Effects. You can read about the API redesign process on the jQuery UI Blog. Although the redesigns introduce breaking changes, 1.9 maintains full compatibility with the 1.8 API by default. This is accomplished by rebuilding the 1.8 API on top of the 1.9 API. The default behavior for all 1.9 releases will be to simultaneously use the 1.8 and 1.9 APIs, deferring to the 1.8 API if there is a conflict. If you would like to load just the 1.9 API without the 1.8 API, you can set the $.uiBackCompat flag to false.

1
2
3
<script src="jquery.js"></script>
<script>$.uiBackCompat = false;</script>
<script src="jquery-ui.js"></script>

This will prevent the initialization of the back-compat layer, allowing you to use the 1.9 API in cases where there is a conflict with the 1.8 API.

link Preparing for jQuery UI 1.10

The API redesigns deprecate a lot of functionality, which will be removed in 1.10. You don't have to wait for the 1.10.0 release in order to find out if your code will work when the 1.8 APIs are removed. You can use the $.uiBackCompat flag to test this with any 1.9 release.

If you find a regression from the 1.8 API, please report it in the bug tracker. Even though the 1.8 API is deprecated, it's important for 1.9 releases not to regress so that users are encouraged to upgrade even if they're not ready to use the new APIs.

link Core

link Added .uniqueId() and .removeUniqueId() methods

(#8361) Many widgets need to generate unique ids for elements. .uniqueId() will check if the element has an id, and if not, it will generate one and set it on the element. It is safe to call .uniqueId() on an element without checking if it already has an id. If/when the widget needs to clean up after itself, the .removeUniqueId() method will remove the id from the element if it was added by .uniqueId() and leave the id alone if it was not. .removeUniqueId() is able to be smart about this because the generated ids have a prefix of "ui-id-".

Let's say you have an element containing some content on the page and you want to add an anchor linking to the element. If you're not sure whether the element already has an id that you can reference, you can use .uniqueId().

1
2
3
4
5
var id = element.uniqueId().attr( "id" );
$( "<a>" )
.attr( "href", "#" + id )
.text( "jump to the content" )
.appendTo( navigationElement );

Later, if you want to restore the element to its original state, you can use .removeUniqueId() to ensure that you only remove the id if it was generated by .uniqueId().

1
element.removeUniqueId();

link Deprecated .disableSelection() and .enableSelection()

(#7755) To quote Mats Palmgren "Preventing the user from selecting stuff is evil." Following that logic, we have deprecated .disableSelection() and .enableSelection().

.disableSelection() and .enableSelection() are planned to be removed in 2.0 but may be removed as early as 1.10.

link Deprecated $.ui.contains

(#5000) jQuery 1.4 added $.contains, with the same API as $.ui.contains. You should replace all uses of $.ui.contains with $.contains; since the APIs are identical, this is a simple search and replace.

$.ui.contains will be removed in 1.10.

link Removed modifier keys from $.ui.keyCode

(#7613) The key codes for modifier keys are not consistent across browsers, so the values provided in $.ui.keyCode were not reliable. In addition, you generally don't want to listen for key presses on meta keys. In almost every situation, you would be listening for another key press and checking if a meta key is being pressed at the same time. The key codes are not useful in this situation, and you should use the event properties such as altKey and shiftKey instead.

The following keys were removed from $.ui.keyCode: ALT, CAPS_LOCK, COMMAND, COMMAND_LEFT, COMMAND_RIGHT, CONTROL, INSERT, MENU, SHIFT, WINDOWS.

link Changed naming convention for .data() keys

(#7810) The naming convention for data stored using .data() was somewhat inconsistent before, with various plugins using various formats. We've now standardized on dashed names, prefixed with the full plugin name. Widget instances now use the full name, including the namespace, e.g., ui-dialog instead of dialog. Tabs now uses ui-tabs-destroy instead of destroy.tabs. Slider now uses ui-slider-handle-index instead of index.ui-slider-handle. Autocomplete now uses ui-autocomplete-item instead of item.autocomplete. Effects now use ui-effect-* instead of ec.storage.*. Some of these were purely internal, and some were useful to users. The ones that were useful to users, specifically the widget instances and autocomplete items, still support the old names, though they are now deprecated.

Non-namespaced widget instances and item.autocomplete will be removed in 1.10.

link Accordion

The Accordion API has been redesigned. You may want to read the discussions behind the changes.

link Added data to the create event

(#7869) The create event now provides header and content data. This makes it easier to write consistent code for initialization and activation.

1
2
3
4
5
6
7
8
$( "#accordion" ).accordion({
create: function( event, ui ) {
// Header that is active on initialization
ui.header
// Panel that is active on initialization
ui.panel
}
});

link Headers no longer require a child anchor element

Accordions used to require a single anchor inside each header. This requirement has been dropped, allowing headers to be as simple or complex as you want. No change is required, though removing the anchors is highly encouraged as they are no longer being automatically removed from the tab order.

Old API:

1
2
3
4
5
6
<div>
<h3><a href="#">Section 1</a></h3>
<p>...</p>
<h3><a href="#">Section 2</a></h3>
<p>...</p>
</div>

New API:

1
2
3
4
5
6
<div>
<h3>Section 1</h3>
<p>...</p>
<h3>Section 2</h3>
<p>...</p>
</div>

link Deprecated changestart event; renamed to beforeActivate

(#6840) The changestart event has been renamed to beforeActivate for consistency with other plugins in jQuery UI. The data provided in the event is the same, but some of the names have changed: newContent is now newPanel and oldContent is now oldPanel. You should replace all uses of the changestart event with the beforeActivate event.

Old API:

1
2
3
4
5
6
7
8
9
10
11
12
$( "#accordion" ).accordion({
changestart: function( event, ui ) {
// Panel that is currently active, about to be deactivated
ui.oldContent
// Header associated with the currently active panel
ui.oldHeader
// Panel that is about to be activated
ui.newContent
// Header associated with the panel that is about to be activated
ui.newHeader
}
});

New API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$( "#accordion" ).accordion({
// CHANGED (previously changestart)
beforeActivate: function( event, ui ) {
// Panel that is currently active, about to be deactivated
// CHANGED (previously oldContent)
ui.oldPanel
// Header associated with the currently active panel
ui.oldHeader
// Panel that is about to be activated
// CHANGED (previously newContent)
ui.newPanel
// Header associated with the panel that is about to be activated
ui.newHeader
}
});

Note: Although the callback name is camelCase, all event names are lowercase; therefore the associated event name is accordionbeforeactivate.

The changestart event will be removed in 1.10.

link Allow Canceling the beforeActivate event

(#6896) The beforeActivate event (previously changestart) is now cancelable. If you prevent the default action inside the beforeActivate event, the panel will not be activated.

1
2
3
4
5
6
7
$( "#accordion" ).accordion({
beforeActivate: function( event, ui ) {
if ( ui.newHeader.text() === "Don't Activate Me" ) {
event.preventDefault();
}
}
});

link Deprecated change event; renamed to activate

(#6842) The change event has been renamed to activate for consistency with other plugins in jQuery UI. Just like the beforeActivate event, the data provided in the event is the same, but some of the names have changed: newContent is now newPanel and oldContent is now oldPanel. You should replace all uses of the change event with the activate event.

The change event will be removed in 1.10.

link Deprecated resize method; renamed to refresh

(#6838) The resize method has been renamed to refresh for consistency with other plugins in jQuery UI. The method currently has the exact same behavior as the old resize method, though it may support adding/removing panels in the future. You should replace all uses of the resize method with the refresh method.

The resize method will be removed in 1.10.

link Deprecated animated option; renamed to animate

(#8600) The animation options for accordion were heavily customized to the implementation details of the accordion plugin. Customizing the animation was difficult and inconsistent with anything else in jQuery UI. The new animate option looks like a standard animation now, with support for easing and duration properties. In addition, you can specify a down option to apply a different animation when the panel being activated has a lower index than the currently active panel. You should replace all users of the animated option with the animate option.

Old API:

1
2
3
$( "#accordion" ).accordion({
animated: "bounceslide"
});

New API:

1
2
3
4
5
6
7
8
9
$( "#accordion" ).accordion({
animate: {
duration: 200,
down: {
easing: "easeOutBounce",
duration: 1000
}
}
});

The animated option will be removed in 1.10.

link Deprecated icons.headerSelected option; renamed to icons.activeHeader

(#6834) The icon for the active header has been renamed from headerSelected to activeHeader to accompany the other changes for consistency with the term "active". You should replace all uses of icons.headerSelected with icons.activeHeader.

Old API:

1
2
3
4
5
6
7
8
$( "#accordion" ).accordion({
icons: {
// Icon for collapsed headers
header: "ui-icon-circle-arrow-e",
// Icon for active header
headerSelected: "ui-icon-circle-arrow-s"
}
});

New API:

1
2
3
4
5
6
7
8
9
$( "#accordion" ).accordion({
icons: {
// Icon for collapsed headers
header: "ui-icon-circle-arrow-e",
// Icon for active header
// CHANGED (previously headerSelected)
activeHeader: "ui-icon-circle-arrow-s"
}
});

The icons.headerSelected option will be removed in 1.10.

link Deprecated autoHeight, clearStyle, and fillSpace options; merged into heightStyle

(#5871) (#5867) The autoHeight, clearStyle, and fillSpace options were all booleans which controlled how the height of each panel was determined. Since these options couldn't all be used together, the API was confusing and there were combinations that were invalid. These have all been merged into a single option, heightStyle, which accepts a string defining which mode to use. The possible values are:

  • auto: All panels will be set to the height of the tallest panel.
  • content: Each panel will be only as tall as its content.
  • fill: The accordion will expand to fill the available space in the accordion's parent.

You should replace all uses of the autoHeight, clearStyle, and fillSpace options with the heightStyle option.

Old API:

1
2
3
$( "#accordion" ).accordion({
fillSpace: true
});

New API:

1
2
3
4
$( "#accordion" ).accordion({
// CHANGED (previously fillSpace: true)
heightStyle: "fill"
});

The autoHeight, clearStyle, and fillSpace options will be removed in 1.10.

link Deprecated activate method

(#6836) The activate method has been deprecated in favor of simply updating the active option. You should replace all calls to the activate method with calls to the option method to change the active option.

Old API:

1
2
// Activate the third panel (zero-based index)
$( "#accordion" ).accordion( "activate", 2 );

New API:

1
2
// Activate the third panel
$( "#accordion" ).accordion( "option", "active", 2 );

The activate method will be removed in 1.10.

link Deprecated navigation and navigationFilter options

(#5869) The navigation and navigationFilter options provided a way to automatically select which panel should be active on initialization based on the URL. This functionality was disabled by default and is only one of many ways that you might want to determine which panel to activate on initialization. As such, we've deprecated this in favor of just handling the logic outside of accordion and setting the active option appropriately. You should remove all uses of the navigation and navigationFilter options.

The navigation and navigationFilter options will be removed in 1.10.

link Deprecated support for activating panels with selectors or collapsing with -1

(#6852) It was previously possible to activate panels using a selector which was used to find a header. It was also possible to use -1 or any falsey value to indicate that no panel should be active and the accordion should be collapsed. Support for selectors has been deprecated and numeric indexes should be used instead. Support for collapsing via -1 has also been deprecated and false should be used instead.

Note: When using the 1.9 API, negative indexes will select from the last panel, similar to .eq().

Support for selectors and collapsing with -1 will be removed in 1.10.

link Removed ui-accordion-disabled class

(#8193) Accordion was adding the ui-accordion-disabled class to disabled headers and panels, which was a remnant of earlier designs. This class has been removed in favor of the generic ui-state-disabled class, which was also being applied. If you were styling the ui-accordion-disabled class, you will need to switch to styling ui-state-disabled.

link Autocomplete

link Added response event

(#6777) There is now a response event that is triggered whenever a response is received, even if the menu will not be shown because there are no results or the autocomplete has become disabled. The array of items is passed as the content property in the event data and can be modified before the menu is shown.

1
2
3
4
5
6
7
$( "#autocomplete" ).autocomplete({
src: [],
response: function( event, ui ) {
// Always add a "jQuery" item
ui.content.push({ label: "jQuery", value: "jQuery" });
}
});

Note: The content is already normalized prior to the response event, so if you modify the data, you should take care to include both label and value properties.

link Added support for contentEditable

(#6914) Autocomplete started with support for input elements, then expanded to support textarea elements, and now even supports editable elements via the contentEditable attribute. Just like textareas, when using autocomplete on editable elements, the up and down arrows will not invoke a search, allowing the user to freely move through the content.

link Synchronous change event

(#7550) Previously, interactions with the menu could shift focus from the text field to the menu itself. This meant that we had to delay the handling of blur events, which caused the change event to be asynchronous. This caused problems in various situations, such as performing validations in the change event, but having a form submit before the event was triggered. We have since found a way to handle the focus changes while still triggering the change event synchronously. It's unlikely that you will need to change any code to accommodate this change, but since the timing of the event has changed, we though it was worth mentioning.

link Blurring a suggestion no longer changes the value of the input

(#7742) Blurring a suggestion in the menu had different behavior based on keyboard navigation or mouse navigation. When using the mouse, the value in the text field would be reset back to the search term. We have removed this behavior, resulting in consistent behavior between mouse and key navigation. This also brings us in line with Firefox's Awesome Bar, which we have been using as a model.

link Added experimental messages option for accessibility

We now use ARIA live regions to announce when results become available and how to navigate through the list of suggestions. The announcements can be configured via the messages option, which has two properties: noResults for when no items are returned and results for when at least one item is returned. In general, you would only need to change these options if you want the string to be written in a different language. The messages option is subject to change in future versions while we work on a full solution for string manipulation and internationalization across all plugins. If you're interested in the messages option, we encourage you to just read the source; the relevant code is at the very bottom of the autocomplete plugin and is only a few lines.

link Dialog

link Added ui-dialog-buttons class

(#7057) Dialogs now have a ui-dialog-buttons class added to the outermost element when the button pane is present. This allows different styling based on whether or not there are buttons in the bottom of the dialog.

link Properly account for padding when calculating height

(#7692) The height of the dialog was previously calculated incorrectly if there was padding on the dialog element. Dialogs now properly account for padding when setting the height of the dialog. While this is just a bug fix, the height of your dialogs will be smaller than they previously were if you were adding padding to the dialog and setting an explicit height via the height option.

link Dialogs return to their previous DOM position on destroy

(#4980) When a dialog is initialized, it is moved to the end of the DOM as a direct child of the body. This ensures that the z-index can be properly applied to bring the dialog in front of the rest of the page. Previously, upon destroy, the dialog would stay at the end of the DOM. Now, the dialog will return to its original position. This is accomplished by tracking the original parent of the dialog. If you were previously moving the dialog back to its original position on destroy, you can remove your workarounds for this.

Note: The dialog does not move back to its original position when closed, only when destroyed.

link Removed beforeclose option

(#5100) The beforeclose option was deprecated in 1.8 in favor of beforeClose and has now been removed. You must replace all uses of the beforeclose option with beforeClose.

Old API:

1
2
3
$( "#dialog" ).dialog({
beforeclose: function() {}
});

New API:

1
2
3
4
$( "#dialog" ).dialog({
// CHANGED (previously beforeclose)
beforeClose: function() {}
});

link Position

The Position API has been redesigned. You may want to read the discussions behind the changes.

link Improved collision detection

(#5284) Previously, the position utility was only smart enough to detect if there was a collision, but not whether applying the collision logic would improve the situation. This resulted in a few cases where applying the collision logic would make the situation worse. For example, an element may be 80% visible, but have a collision and flipping may result in the element only being 20% visible. The flip and fit collision methods have been adjusted to only apply if they make the positioning improve (for fit that means limiting how far the element can shift).

link Added new collision mode: flipfit

(#7492) Position now supports "flipfit" as a collision mode. When there is a collision, this mode will first run the flip collision logic followed by the fit collision logic. This allows the element to be adjusted by the best mode possible.

1
2
3
4
5
6
element.position({
my: "left top",
at: "right top",
of: otherElement,
collision: "flipfit"
});

link Added within option for improved collision handling

(#5645) Collision detection was previously only supported for collisions with the window. The new within option allows you to specify an element to use to calculate the collision boundaries. The value can be an element, document, window, jQuery object, or selector. The within option is optional and defaults to window.

1
2
3
4
5
6
element.position({
my: "left top",
at: "right top",
of: otherElement,
within: "#container"
});

link Added support for percent-based offsets

(#7028) Offsets can now be specified as a percentage of the element's size or as a percentage of the target's size. Percentages placed inside the my option will be based on the element's size and percentages placed inside the at option will be based on the target's size.

1
2
3
4
5
element.position({
my: "left+10% top+10%",
at: "right top",
of: otherElement
});

Note: Offsets are now merged into the my and at options. See below.

link Deprecated offset option; merged into my and at

(#6981) The offset option has been deprecated and offsets have been merged into the my and at options. The form for a position is now the named position, optionally followed by a plus or minus and then an offset. In addition, offsets now support percentages (see above). You should replace all uses of the offset option with offsets placed inside the my and/or at options.

Old API:

1
2
3
4
5
6
element.position({
my: "left top",
at: "right top",
of: otherElement,
offset: "10 -20"
});

New API:

1
2
3
4
5
6
element.position({
// CHANGED (previously used offset option in addition to my option)
my: "left+10 top-20",
at: "right top",
of: otherElement
});

Note: The offset option will be removed in 1.10.

link Added positioning feedback to the using callback

(#5937) There are quite a few use cases in which it's important to know where the element being positioned ended up relative to the target element. For example, if you're creating a tooltip or providing additional information about an item and you want to have the element pointing to the target to provide some additional context. The position utility now exposes a lot of detail about the positioning of the element and the target in order to handle these types of scenarios. In order to get access to this information, you'll need to provide a using callback.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
element.position({
using: function( position, data ) {
// Information about the element being positioned
data.element
// jQuery object containing the element
data.element.element
// Left offset of the element
data.element.left
// Top offset of the element
data.element.top
// Width of the element (including padding and border)
data.element.width
// Height of the element (including padding and border)
data.element.height
// Information about the target element (same structure as data.element)
data.target
// Where the element is relative to the target
// Possible values: left, right, center
data.horizontal
// Possible values: top, bottom, middle
data.vertical
// Which direction is weighted more in terms of the general direction
// between the two elements
data.important
// When providing a using callback, the position of the element is
// calculated, but the element is not moved. You will need to position
// the element yourself:
$( this ).css( position );
}
});

link Tabs

The Tabs API has been redesigned. You may want to read the discussions behind the changes.

link Added refresh method

(#7140) Tabs now has a refresh method which will detect tabs that have been added or removed. Simply modify the underlying markup the same way you would prior to initialization and then call the refresh method and the widget will take care of everything else. See below in the notes for the deprecated add and remove methods for examples of how to use the refresh method.

link Added heightStyle option

(#8345) Tabs now has a heightStyle option which controls how the height of the panels are determined. This matches the functionality of accordion's new heightStyle option. The possible values are:

  • auto: All panels will be set to the height of the tallest panel.
  • content: Each panel will be only as tall as its content.
  • fill: The panels will expand to fill the available space in the tab set's parent.

link Added data to the create event

(#7868) The create event now provides tab and content data. This makes it easier to write consistent code for initialization and activation.

1
2
3
4
5
6
7
8
$( "#tabs" ).tabs({
create: function( event, ui ) {
// Tab that is active on initialization
ui.tab
// Panel that is active on initialization
ui.panel
}
});

link New keyboard handling and improved accessibility

(#3079) (#7845) Tabs now has full ARIA support and proper keyboard navigation. The UP, DOWN, LEFT, RIGHT, HOME, and END keys navigate through the tabs. SPACE and ENTER both activate panels, but ENTER can also collapse panels (if the collapsible option is enabled). Navigating through the tabs does not immediately activate the panels; there is a short delay so that users can navigate through the tabs without activating each tab along the way. Navigating while holding CTRL will prevent the automatic activation, making it possible for users of assistive technologies such as screen readers to have as much time as they need while navigating without activating each tab. ALT+PAGE UP and ALT+PAGE DOWN will move focus to the previous or next tab, respectively, and immediately activate the tab (this works regardless of whether focus is on the tabs or in a panel). When focus is in a tab panel, CTRL+UP will move focus to the associated tab.

link Deprecated fx option; use show and hide options

(#8319) The fx option has been deprecated in favor of new show and hide options. The show and hide options provide more customization over animations. See below, in the Widget section, for more details about the show and hide options. You should replace all uses of the fx option with show and hide.

The fx option will be removed in 1.10.

link Deprecated ajaxOptions and cache options; added beforeLoad event

(#7131) The ajaxOptions and cache options have been deprecated in favor of a new beforeLoad event. The event receives a jqXHR object and the settings object that will be passed to jQuery.ajax(). The settings passed to the beforeLoad event can be modified, allowing the functionality that the ajaxOptions option previously provided. If you prevent the default action of the event, then the ajax request will not be made and the tab will be immediately shown. This provides the functionality that the cache option provided, but with much more fine-grained control. In addition, you can now interact with the jqXHR object, allowing additional functionality, such as setting headers.

Old API:

1
2
3
4
5
6
$( "#tabs" ).tabs({
ajaxOptions: {
username: "foo",
password: "bar"
}
});

New API:

1
2
3
4
5
6
$( "#tabs" ).tabs({
beforeLoad: function( event, ui ) {
ui.ajaxSettings.username = "foo";
ui.ajaxSettings.password = "bar";
}
});

Old API:

1
2
3
$( "#tabs" ).tabs({
cache: true
});

New API:

1
2
3
4
5
6
7
8
9
10
11
12
$( "#tabs" ).tabs({
beforeLoad: function( event, ui ) {
if ( ui.tab.data( "loaded" ) ) {
event.preventDefault();
return;
}
ui.jqXHR.success(function() {
ui.tab.data( "loaded", true );
});
}
});

The ajaxOptions and cache options will be removed in 1.10.

link Deprecated url method and use of title attribute; use aria-controls attribute

(#7132) The url method has been deprecated in favor of leaving the href attribute unmodified even for remote tabs. The href attribute will point to the actual resource and the aria-controls attribute will point to the associated panel. This means that the title attribute will no longer be used to specify a custom panel id.

The url method and use of the title attribute will be removed in 1.10.

link Deprecated abort method

(#7133) As mentioned above, the new beforeLoad event exposes the jqXHR object for ajax requests. Having access to the jqXHR object gives you full control over the requests. As a result, the abort method has been deprecated, since you can now directly abort the request.

Old API:

1
$( "#tabs" ).tabs( "abort" );

New API:

1
2
3
4
5
$( "#tabs" ).tabs({
beforeLoad: function( event, ui ) {
ui.jqXHR.abort();
}
});

The abort method will be removed in 1.10.

link Deprecated spinner option

(#7134) The spinner option commonly caused confusion because it required the tab to contain exactly one span in order to show the spinner. The functionality was also fairly limited, allowing the injection of HTML, but no other customizations, such as adding a class to the tab. This option has also been deprecated in favor of using the beforeLoad event. Now that there are events before (beforeLoad) and after (load), it's easy to implement customized functionality while remote tabs are loading.

The spinner option will be removed in 1.10.

link Deprecated selected option; renamed to active

(#7135) The selected option has been renamed to active for consistency with other plugins in jQuery UI. You should replace all uses of the selected option with the active option.

The selected option will be removed in 1.10.

link Deprecated select event; renamed to beforeActivate

(#7136) The select event has been renamed to beforeActivate for consistency with other plugins in jQuery UI. The data provided in the event has also been changed. The tab property is now newTab and refers to the list item instead of the anchor. The panel property is now newPanel. Both tab and panel are now jQuery objects instead of DOM elements. The index property has been removed. You should replace all uses of the select event with the beforeActivate event.

Old API:

1
2
3
4
5
6
7
8
9
10
$( "#tabs" ).tabs({
select: function( event, ui ) {
// Panel that is about to be activated
ui.panel
// Tab associated with the panel that is about to be activated
ui.tab
// Index of the tab that is about to be activated
ui.index
}
});

New API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$( "#tabs" ).tabs({
// CHANGED (previously select)
beforeActivate: function( event, ui ) {
// Panel that is currently active, about to be deactivated
// ADDED
ui.oldPanel
// Tab associated with the currently active panel
// ADDED
ui.oldTab
// Panel that is about to be activated
// CHANGED (previously panel)
ui.newPanel
// Tab associated with the panel that is about to be activated
// CHANGED (previously tab)
ui.newTab
// Index can be calculated if needed
ui.newTab.index()
}
});

Note: Although the callback name is camelCase, all event names are lowercase; therefore the associated event name is tabsbeforeactivate.

The select event will be removed in 1.10.

link Deprecated show event; renamed to activate

(#7137) The show event has been renamed to activate for consistency with other plugins in jQuery UI. Just like the beforeActivate event, the data provided has changed: tab is now newTab, panel is now newPanel, index has been removed, and oldTab and oldPanel have been added. Unlike the show event, the activate event is not triggered on initialization. If you need to perform some action in response to the initial tab being shown, you should listen to the create event. You should replace all uses of the show event with the activate event.

The show event will be removed in 1.10.

link Deprecated select method

(#7138) The select method has been deprecated in favor of just updating the active option. You should replace all calls to the select method with calls to the option method to change the active option.

Old API:

1
2
// Activate the third tab (zero-based index)
$( "#tabs" ).tabs( "select", 2 );

New API:

1
2
// Activate the third panel
$( "#tabs" ).tabs( "option", "active", 2 );

The select method will be removed in 1.10.

link Deprecated add and remove methods and events; use refresh method

(#7141) The add and remove methods have been deprecated in favor of the refresh method, which brings consistency with other plugins in jQuery UI. With the add and remove methods being deprecated, the associated add and remove events have been deprecated as well. You should replace all uses of the add and remove methods with direct markup changes and the refresh method.

Old API:

1
$( "#tabs" ).tabs( "remove", 2 );

New API:

1
2
3
4
5
6
7
8
// Remove the tab
var tab = $( "#tabs" ).find( ".ui-tabs-nav li:eq(2)" ).remove();
// Find the id of the associated panel
var panelId = tab.attr( "aria-controls" );
// Remove the panel
$( "#" + panelId ).remove();
// Refresh the tabs widget
$( "tabs" ).tabs( "refresh" );

Old API:

1
$( "#tabs" ).tabs( "add", "/remote/tab.html", "New Tab" );

New API:

1
2
3
$( "<li><a href='/remote/tab.html'>New Tab</a></li>" )
.appendTo( "#tabs .ui-tabs-nav" );
$( "#tabs" ).tabs( "refresh" );

The add and remove methods and events will be removed in 1.10.

link Deprecated idPrefix, tabTemplate, and panelTemplate options; use refresh method

(#7139) As mentioned above, the add and remove methods have been deprecated. As a result, the idPrefix, tabTemplate, and panelTemplate options have been deprecated as well. You should replace all uses of the idPrefix, tabTemplate, and panelTemplate options with the markup you would like to use.

The idPrefix, tabTemplate, and panelTemplate options will be removed in 1.10.

link Deprecated enable and disable events

(#7142) Tabs was the only plugin that triggered enable and disable events. These events have been deprecated to create consistency between tabs and the other plugins in jQuery UI.

The enable and disable events will be removed in 1.10.

link Deprecated length method

(#7143) The length method wasn't very useful and the number of tabs can easily be determined by checking the number of elements in the list. As a result, the length method has been deprecated.

The length method will be removed in 1.10.

(#7144) Support for cookies is not part of the core functionality for tabs and there are many ways to manage state across page loads. Therefore, the cookie option has been deprecated in favor of setting the active option appropriately during initialization.

The cookie option will be removed in 1.10.

link CSS class name changes for consistency

(#7146) The ui-tabs-selected class has been renamed to ui-tabs-active. The ui-state-processing class has been renamed to ui-tabs-loading. The ui-tabs-hide class has been removed and tabs are now hidden using .hide(). If you were styling the ui-tabs-selected or ui-state-processing classes, you will need to switch to styling ui-tabs-active and ui-tabs-loading.

link Removed rotate method

(#5939) The rotate method has been removed as it is fairly uncommon and unrelated to the core functionality of tabs. Christopher McCulloh has implemented an extension based on the original code, which will add back the rotate method along with some additional rotation functionality.

link Widget

link The widget method now maintains the stack

(#5732) The widget method provides a way to access widget-generated content, such as the wrapper of a dialog or the menu of an autocomplete widget. Previously the return value was a new jQuery object which had no stack. Now the return value is pushed on to the existing stack that was used when calling the widget method. This allows you to call .end() after calling the widget method and get back to your previous selection.

link Added document and window properties

(#7801) In some cases, widgets are used in different windows than the one in which the code was loaded. It's easy to fall into a trap where this won't work if you reference globals such as window or document. In order to avoid falling into this trap, we've added window and document properties to all widgets which are jQuery objects that contain the correct values based on the element associated with the widget instance.

link Added _delay method

(#8470) Widgets now have a _delay method which functions similar to setTimeout except that it maintains the context so that this is the plugin instance. You can pass either a function or the name of a method on the widget for the first parameter. The second parameter is the delay in milliseconds and is optional, with a default value of 0.

link Added _getCreateEventData method for providing data in the create event

(#8045) All widgets trigger a create event upon instantiation, but there was previously no way to provide data for this event. To remedy this, we've added a new, _getCreateEventData, which should return the data to provide in the create event. If you're building a widget and you'd like to provide data, simply add a _getCreateEventData method which returns an object containing the data you would like to provide. If you don't have any data to provide, you can just omit this method.

link Added _destroy method

(#5056) There are very few places in which common functionality requires you to call into a parent method in order for a widget to be implemented properly. The destroy method has traditionally been such a case, where all widgets need to implement widget-specific destroy logic, but also call into the base destroy method for proper cleanup. The base destroy method now calls _destroy so that you no longer need to worry about this. Existing destroy methods that call into the parent will continue to work, but we recommend changing to _destroy and removing the call to the parent destroy method.

Old API:

1
2
3
4
5
6
7
8
$.widget( "demo.widget", {
destroy: function() {
// Invoke the base destroy method
$.Widget.prototype.destroy.call( this );
// Perform widget-specific cleanup
...
}
});

New API:

1
2
3
4
5
6
$.widget( "demo.widget", {
_destroy: function() {
// Perform widget-specific cleanup
...
}
});

link Added $.widget.extend to handle array references

(#7718) Since widgets perform a deep extend on options, it was not previously possible to pass an array and keep a reference to it from outside of the widget. In order to deal with this, we've add $.widget.extend which performs a deep extend on objects, but copies arrays by reference. $.widget.extend is now used for all option merging inside widgets.

link Added _hoverable and _focusable methods

(#3673) Almost every widget applies styles on hover and focus, so we've added two new methods to simplify the implementation across all of the plugins. The _hoverable method adds the ui-state-hover class on hover and the _focusable method adds the ui-state-focus class on focus. Both methods are smart enough to not add the class if the widget is disabled. In addition, the widgets will automatically remove the associated events and classes if the widget instance is destroyed. Simply pass a jQuery object containing the elements you want to respond to hover or focus and everything will be hooked up for you.

1
this._hoverable( this.element.find( ".hoverable-elements" ) );

link Added _show and _hide methods to support show and hide options

(#3772) There has historically been quite a bit of inconsistency with respect to how effects are applied to widgets. Each widget had its own API and differing levels of support for various effect types and settings. We now have a standardized implementation which is implemented in the base widget and exposed as the _show and _hide methods. These methods are designed to support new common options named show and hide. These methods/options provide support for any combination of settings and effects, from no animation to core animations such as fade and slide to advanced jQuery UI effects such as fold and explode, with support for customized easings and durations.

link Options API

The following examples use the show option. The hide option has the same support, but the animations are reversed, e.g., .fadeOut() instead of .fadeIn().

If the value is falsey, then no animation will occur and the element will be shown immediately.

1
2
// Equivalent: .show()
show: null

If the value is true, then the element will fade in with the default duration and the default easing.

1
2
// Equivalent: .fadeIn()
show: true

If the value is a number, then the element will fade in with the specified duration using the default easing.

1
2
// Equivalent: .fadeIn( 1000 )
show: 1000

If the value is the name of a jQuery method, then that method will be used with the default duration and default easing.

1
2
// Equivalent: .slideDown()
show: "slideDown"

If the value is the name of a jQuery UI effect, then that effect will be used with the default duration and default easing.

1
2
// Equivalent: .show( "fold" )
show: "fold"

If the value is an object, then effect, duration, and easing properties may be provided. If the effect property contains the name of a jQuery method, then that method will be used; otherwise it is assumed to be the name of a jQuery UI effect. When using a jQuery UI effect that supports additional settings, you may include those settings in the object and they will be passed to the effect. If duration or easing is omitted, then the default values will be used. If the effect is omitted, then "fadeIn" will be used.

1
2
3
4
5
6
7
8
9
10
11
12
13
// Equivalent: .slideDown( 500, "easeOutBounce" )
show: {
effect: "slideDown",
duration: 500,
easing: "easeOutBounce"
}
// Equivalent: .show({ effect: "explode", duration: 500, pieces: 25 })
show: {
effect: "explode",
duration: 500,
pieces: 25
}

link Method API

The _show and _hide methods accept three parameters: the element to show/hide, the options, and a callback. The usage will generally look like:

1
2
3
this._show( someElement, this.options.show, function() {
// Do stuff after the element is shown
});

link Added support for working with nested options via the option method

(#7035) (#7459) Some widgets have nested options, such as button's icons.primary option. The option method now supports getting and setting nested options. It was previously not possible to get or set icons.primary by itself, you could only work with the entire icons option. You can now get or set options as deep as you want by simply providing the dot-separated path for the option you want to work with.

1
2
3
4
5
// Get the icons.primary option
var primaryIcon = $( "#button" ).button( "option", "icons.primary" );
// Set the icons.primary option
$( "#button" ).button( "option", "icons.primary", "ui-icon-wrench" );

link Added _super and _superApply methods

(#6861) Widgets support inheritance and all widgets have at least one parent, with $.Widget being the default parent. Up until now there hasn't been anything in the widgets to make calling methods on the parent easy, resulting in code like $.Widget.prototype._setOption.call( this, "foo", "bar" ). With the addition of _super and _superApply, calling methods on the parent is now cleaner and you no longer need to have a hard-coded reference to the parent's prototype. The _super method will invoke the method of the same name as the method that's currently being run and will pass through any parameters. The _superApply method works the same way, but accepts an array of parameters.

Old API:

1
$.Widget.prototoype._setOption.call( ths, "foo", "bar" );

New API:

1
this._super( "foo", "bar" );

*Note: Assumes that this is called from inside _setOption.

Old API:

1
$.Widget.prototype._setOption.apply( this, arguments );

New API:

1
this._superApply( arguments );

*Note: Assumes that this is called from inside _setOption.

link Added _on and _off methods for simplified event binding

(#5207) (#7795) (#8385) Almost every widget needs to bind event handlers for part of its functionality. The widget then needs to track the event handlers or bind them using a common namespace so that they can be unbound when the widget instance is destroyed. In addition, most event handlers should not run if the widget is disabled. We've added two new methods, _on and _off, to handle these issues automatically. These methods support delegation and will ensure that two instances of the same widget won't interfere with each other even if they both bind to the same element(s). The _on method accepts two parameters: the element to bind to and an events-map. The first parameter can be anything that jQuery accepts, such as a selector, DOM element, or jQuery object. The keys of the events-map can be the name of the event to listen for or the name of an event followed by a space and a selector for delegated event handlers. The values of the events-map can either be a function or a string containing the name of a method to call. If a string is provided, then the method lookup is performed at the time of the event, which means if the method is changed after the call to _on, the new method will be invoked when the event occurs. Inside the event handlers, this is the plugin instance.

1
2
3
4
5
6
7
8
9
this._on( someElement, {
mousedown: function( event ) {
this._handleDown();
},
mouseup: "_handleUp",
"click .other-element": function( event ) {
this._handleClick( event.target );
}
});

link Added defaultElement property for auto-generating elements

(#8473) Widgets can now be instantiated without an element and an element will automatically be generated during instantiation. By default the element will be <div> but the widget can define any string of HTML in the defaultElement property on the prototype and that will be used to generate the element. This only comes into play when instantiating a widget instance directly.

1
2
var dialog1 = $.ui.dialog();
var dialog2 = $.ui.dialog({ title: "Hooray" });

link Improved API for direct instantiation

(#6891) Direct instantiation of widgets used to require the new keyword or calling the _createWidget method directly. Now calling the constructor without the new keyword will always instantiate the widget, and calling with new will only instantiate the widget if at least one parameter is passed (this is needed for simple inheritance).

1
2
3
4
5
var dialog1 = $.ui.dialog();
var dialog2 = $.ui.dialog( options );
var dialog3 = $.ui.dialog( options, element );
var dialog4 = new $.ui.dialog( options );
var dialog5 = new $.ui.dialog( options, element );

link Allow non-DOM based widgets

(#6895) Widgets can now be self-contained and not tied to DOM elements. In order to create a widget that is not tied to the DOM, the defaultElement must be set to null (see above for details about defaultElement). For widgets that are not tied to the DOM, all events triggered by the widget will occur directly on the instance.

1
2
3
4
5
var instance = $.demo.widget();
$( instance ).on( "someevent", function( event ) {
// Handle the event
});
instance.someMethod();

link Allow redefining widgets to create extensions

(#6937) Previously the only way to extend a widget was to modify the prototype directly. Now, widgets can be redefined through $.widget just like any other widget that inherits from another widget. The ability to redefine widgets combined with the new _super and _superApply methods provides a much nicer API for creating widget extensions. To redefine a widget, just pass the existing constructor as the base and provide the same name.

Old API:

1
2
3
4
5
var open = $.ui.dialog.prototype.open;
$.ui.dialog.prototype.open = function() {
console.log( "The dialog is being opened." );
open.call( this );
};

New API:

1
2
3
4
5
6
$.widget( "ui.dialog", $.ui.dialog, {
open: function() {
console.log( "The dialog is being opened." );
this._super();
}
});

It's possible to redefine a widget that other widgets are already inheriting from as well. Doing so will not affect any instances that have already been created, but it's unlikely that you would be redefining a widget after instantiating any instances anyway.

link Moved version numbers into prototypes

(#7436) Version numbers have been moved into the widget prototypes so that they persist on the instances. This allows you to tell which version was used for each widget instance if multiple version of jQuery UI are loaded on a page. The version property still exists directly on the constructor as well for backward compatibility. If you're creating widgets with the widget factory and you're setting version numbers on your constructors, you should move the version to the prototypes; the version will automatically be copied to the constructor for you.

link Deprecated use of metadata plugin

(#7191) All widgets currently support use of the metadata plugin to specify options that should be used on instantiation. With the addition of _getCreateOptions in 1.8.6, there was no longer a need for this to be built-in. Use of the metadata plugin is now deprecated. You should remove all uses of the metadata plugin for specifying options or implement _getCreateOptions to behave how you want.

Use of the metadata plugin will be removed in 1.10.

link Deprecated widgetBaseClass property; renamed to widgetFullName

(#8154) The widgetBaseClass property was originally added for prefixing class names, but is useful for more than just class names. As such, we have renamed this property to widgetFullName. You should replace all uses of widgetBaseClass with widgetFullName.

The widgetBaseClass property will be removed in 1.10.

link Widget pseudo selectors are now lowercase

(#8433) Widgets auto-create selectors based on the widget name. For example, a widget created with $.widget( "foo.barBaz", {} ) would create a :foo-barBaz selector. Sizzle treats this the same as the lowercase version :foo-barbaz. However, in order to be consistent with all standard selectors, we have changed the selectors to be generated as all lowercase.

link Calling an invalid method now throws an error

(#5972) Previously, calling a non-existent or non-public method would result in a no-op. This will now result in an error being thrown. Technically, $.error will be called, which defaults to throwing an Error.

link Effects

link Renamed all effects files

All effects files have been renamed from jquery.effects.*.js to jquery.ui.effect-*.js and jquery.effects.core.js has been renamed to jquery.ui.effect.js.

link Rewrote all easing equations to only rely on state

(#8115) Easing questions are provided with a lot of information: the starting and ending values, the current state (in percentage), how long (in milliseconds) the animation has been running, and how long the animation will run in total. In reality, only the current state is necessary. All of the easing equations have therefore been simplified to only rely on state and the implementations have been changed for a dramatic saving in file size. In the process, a few equations were changed, but those that were changes are extremely close to their original equations and it is unlikely that anyone can notice the differences without transposing graphs of the old and new equations on top of each other.

link Added children option to class animations

(#3939) The class animation methods (addClass, removeClass, and toggleClass) now support a children option, which will also animate descendant elements. This option defaults to false due to the overhead of calculating which styles to animate on large DOM trees.

1
2
3
4
element.addClass( "foo", {
duration: 1000,
children: true
});

link Blind effect's direction option now supports up, down, left, and right

(#4880) The blind effect already supported vertical and horizontal for the direction option. It now accepts up, down, left, and right, creating consistency with other effects such as drop and slide. vertical is the same as up and horizontal is the same as left.

link Upgraded to jQuery Color 2.0.0

(#3806) (#4372) (#5215) jQuery UI's core effects file contains a copy of jQuery Color, which has recently received a major upgrade. jQuery UI now includes jQuery Color 2.0.0, which brings lots of new features and bug fixes. We encourage you to read the jQuery Color documentation for full details.

link Redesigned effects API

(#7060) (#7103) (#7318) Effects have undergone a minor redesign to clean up the API. Individual effects are now defined on $.effects.effect rather than directly on $.effects. This makes it possible to distinguish between actual effects and helper methods. Effects now automatically handle queuing and are passed a callback to invoke when the animation is complete. In addition, there are no more nested options. Effect-specific options are now merged into the main options, sitting alongside duration, easing, etc. These changes only apply to effects that live in the new $.effects.effect namespace; effects that live in $.effects still use the old API, but are now deprecated. If you have custom effects, you should upgrade them to the new API.

Old API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$.effects.rgb = function( options ) {
return this.queue(function() {
var element = $( this ),
color = "rgb(" +
(options.options.red || 128) + "," +
(options.options.green || 128) + "," +
(options.options.blue || 128) + ")";
element.animate({
backgroundColor: color
}, {
queue: false,
duration: options.duration,
easing: options.easing,
complete: function() {
if ( options.complete ) {
options.complete.apply( this, arguments );
}
element.dequeue();
}
});
});
};

New API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// CHANGED (previously $.effects.rgb)
// CHANGED (previously only had options parameter)
$.effects.effect.rgb = function( options, done ) {
// CHANGED no more .queue() or return value
var element = $( this ),
color = "rgb(" +
// CHANGED (previously options.options)
(options.red || 128) + "," +
(options.green || 128) + "," +
(options.blue || 128) + ")";
element.animate({
backgroundColor: color
}, {
queue: false,
duration: options.duration,
easing: options.easing,
// CHANGED (previously required manual dequeuing and options.complete)
complete: done
});
};

Support for effects in $.effects will be removed in 1.10.

link Theme

link Reversed ui-icon-radio-on and ui-icon-radio-off.

(#7475) The icons for the on and off states were reversed, causing ui-icon-radio-on to show an empty radio and ui-icon-radio-off to show a more solid radio. If you are using these classes, you will need to reverse the classes that you're using.

link Build System

link Removed ant build; replaced with grunt

All jQuery projects now have new build processes, built on top of grunt. Grunt is a task-based command line build tool for JavaScript projects. Our projects are written in JavaScript, our build files (Gruntfiles) are written in JavaScript, and our build tool (grunt) is written in JavaScript. It's JavaScript all the way down! This change brings a lot of benefits. Our build process is now written in a language that the entire team is familiar with, and we have as much flexibility as we want. We're also able to easily share portions of our build processes across our various projects. In addition, our build process now works on all major operating systems.

To setup the build system you'll first need to install node and then install jQuery UI's dependencies. Once you have node installed, run the following commands from the root of your jQuery UI checkout:

1
2
npm install -g grunt
npm install

Here are just a few of the features that are available:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Validate the JavaScript files using JSHint
grunt lint
# Validate the CSS files using CSSLint
grunt csslint
# Validate the HTML files using validator.nu
grunt htmllint
# Run all unit tests in PhantomJS
grunt qunit
# Build minified and concatenated files
grunt build